from django.contrib.auth.backends import ModelBackend
import re

from itsdangerous import BadData

from .models import User
from itsdangerous import TimedJSONWebSignatureSerializer as Serializer
from django.conf import settings

'''
系统的方法是 通过用户名来实现登陆
我们的需求是 通过用户名或者是手机号 来实现登陆

系统的函数(方法)不能满足我们需求的时候,我们就重写


抽取/封装的思想

为什么要封装/抽取
    1.为了解耦
    2.为了复用

封装/抽取的步骤
    1.定义一个方法/函数,把要抽取的代码复制过去
    2.哪里有问题改哪里,没有的参数以变量的形式传递,注意是否有返回值
    3.验证抽取的方法,验证没有问题,就把原代码删除

什么时候封装/抽取
    1.当几行代码(1,2,n行)实现了一个小功能 就可以抽取
    2.当我们的功能在第二次重复出现的时候就要封装
'''


def get_user_by_username(username):
    try:
        if re.match(r'^1[3-9]\d{9}$', username):
            # 手机号登录
            user = User.objects.get(mobile=username)
        else:
            # 用户名登录
            user = User.objects.get(username=username)
    except User.DoesNotExist:
        return None
    else:
        return user


class UsernameMobileAuthBackend(ModelBackend):
    # 此方法在后台登陆验证重新编写
    def authenticate(self, request, username=None, password=None, **kwargs):
        """
        重写认证方法，实现多账号登录
        :param request: 请求对象
        :param username: 用户名
        :param password: 密码
        :param kwargs: 其他参数
        :return: user
        """
        # 根据传入的username获取user对象。username可以是手机号也可以是账号
        user = get_user_by_username(username)
        # 校验user是否存在并校验密码是否正确
        if user and user.check_password(password):
            return user


# 生成邮箱验证连接
def generate_verify_email_url(user):
    """
    user: 当前登录用户
    return verify_url
    """
    serializer = Serializer(settings.SECRET_KEY, expires_in=3600)
    data = {'user_id': user.id, 'email': user.email}
    # 进行数据加密
    token = serializer.dumps(data).decode()
    # verify_url = settings.EMAIL_VERIFY_URL + '?token=' + token
    verify_url = settings.EMAIL_VERIFY_URL + '?token=%s'% token
    return verify_url


# 验证邮箱链接
def check_verify_email_token(token):
    """
      验证token并提取user
      token: 用户信息签名后的结果
      return user, None
      """
    serializer = Serializer(settings.SECRET_KEY, expires_in=3600)
    try:
        data = serializer.loads(token)
    except BadData:
        return None
    else:
        user_id = data.get('user_id')
        email = data.get('email')
        try:
            user = User.objects.get(id=user_id, email=email)
        except User.DoesNotExist:
            return None
        else:
            return user

